package dht.cleaners;

import dht.identifier.identifier.Identifier;
import dht.node.DHTNodeModel;
import dht.node.DHTNodeRow;
import sun.security.util.BitArray;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;

/**
 * Created by IntelliJ IDEA.
 * User: gvennet
 * Date: 28.03.2010
 * Time: 16:48:28
 */
public class TreeCleaner implements NodeModelCleaner, Runnable
{
	private DHTNodeModel nodeModel;

	private final Identifier identifier;

	public TreeCleaner(Identifier identifier)
	{
		this.identifier = identifier;
	}

	@Override
	public void clean()
	{
		if (nodeModel != null)
		{
			int idLength = identifier.getByteArray().length * 8;
			List<DHTNodeRow> nodes = nodeModel.getNodes();
			if (nodes.size() == nodeModel.getMaxSize())
			{
				BitArray bitArray = new BitArray(idLength, identifier.getByteArray());
				boolean[] booleanId = bitArray.toBooleanArray();
				ArrayList<boolean[]> path = new ArrayList<boolean[]>();
				for (int i = 1; i < idLength; i++)
				{
					boolean[] reverse = new boolean[i];
					System.arraycopy(booleanId, 0, reverse, 0, i);
					reverse[i - 1] = !reverse[i - 1];
					path.add(reverse);
				}
				List<DHTNodeRow> copy = nodeModel.getNodes();

				Collection collection = getRows(path, nodeModel.getMaxSize(), copy);

				for (DHTNodeRow row : nodeModel.getNodes())
				{
					if (!collection.contains(row))
					{
						nodeModel.getNodes().remove(row);
					}
				}
			}
		}
	}

	@Override
	public void setNodeModel(DHTNodeModel nodeModel)
	{
		this.nodeModel = nodeModel;
	}

	@Override
	public void run()
	{
		clean();
	}

	private List<DHTNodeRow> getRows(ArrayList<boolean[]> path, int maxNodes, List<DHTNodeRow> copy)
	{
		List<DHTNodeRow> list = new ArrayList<DHTNodeRow>();
		for (int i = path.size() - 1; i >= 0; i--)
		{
			for (DHTNodeRow row : copy)
			{
				if (list.size() <= maxNodes)
				{
					BitArray bitArray = new BitArray(path.get(i).length, row.getId().getByteArray());
					boolean[] booleanId = bitArray.toBooleanArray();

					if (Arrays.equals(booleanId, path.get(i)))
					{
						list.add(row);
						break;
					}
				}
			}
			copy.remove(list.get(list.size() - 1));
		}
		return list;
	}
}
